{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Running Example"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "import torch\n",
    "import torch.nn as nn\n",
    "from model import DigitClassifier\n",
    "from pipeline import get_data_loader\n",
    "from train import train\n",
    "from eval import eval\n",
    "from visualization import visualize_predictions"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "check_point_save_path = \"./checkpoint/number_classification_checkpoint.pth\"\n",
    "data_path = \"./data/MNIST\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Model init 初始化模型、损失函数和优化器\n",
    "device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n",
    "model = DigitClassifier().to(device)\n",
    "criterion = nn.CrossEntropyLoss()\n",
    "optimizer = torch.optim.Adam(model.parameters(), lr=0.001)\n",
    "train_loader, test_loader = get_data_loader(data_path)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Train Epoch: 1 [0/60000 (0%)]\tLoss: 2.296936\n",
      "Train Epoch: 1 [6400/60000 (11%)]\tLoss: 0.101863\n",
      "Train Epoch: 1 [12800/60000 (21%)]\tLoss: 0.180490\n",
      "Train Epoch: 1 [19200/60000 (32%)]\tLoss: 0.013595\n",
      "Train Epoch: 1 [25600/60000 (43%)]\tLoss: 0.103551\n",
      "Train Epoch: 1 [32000/60000 (53%)]\tLoss: 0.085227\n",
      "Train Epoch: 1 [38400/60000 (64%)]\tLoss: 0.131192\n",
      "Train Epoch: 1 [44800/60000 (75%)]\tLoss: 0.041498\n",
      "Train Epoch: 1 [51200/60000 (85%)]\tLoss: 0.127996\n",
      "Train Epoch: 1 [57600/60000 (96%)]\tLoss: 0.036361\n",
      "\n",
      "Test set: Average loss: 0.0001, Accuracy: 9738/10000 (97.38%)\n",
      "\n",
      "Train Epoch: 2 [0/60000 (0%)]\tLoss: 0.016726\n",
      "Train Epoch: 2 [6400/60000 (11%)]\tLoss: 0.007014\n",
      "Train Epoch: 2 [12800/60000 (21%)]\tLoss: 0.002146\n",
      "Train Epoch: 2 [19200/60000 (32%)]\tLoss: 0.009559\n",
      "Train Epoch: 2 [25600/60000 (43%)]\tLoss: 0.111724\n",
      "Train Epoch: 2 [32000/60000 (53%)]\tLoss: 0.081379\n",
      "Train Epoch: 2 [38400/60000 (64%)]\tLoss: 0.016203\n",
      "Train Epoch: 2 [44800/60000 (75%)]\tLoss: 0.054947\n",
      "Train Epoch: 2 [51200/60000 (85%)]\tLoss: 0.071113\n",
      "Train Epoch: 2 [57600/60000 (96%)]\tLoss: 0.044266\n",
      "\n",
      "Test set: Average loss: 0.0000, Accuracy: 9842/10000 (98.42%)\n",
      "\n",
      "Train Epoch: 3 [0/60000 (0%)]\tLoss: 0.048033\n",
      "Train Epoch: 3 [6400/60000 (11%)]\tLoss: 0.008040\n",
      "Train Epoch: 3 [12800/60000 (21%)]\tLoss: 0.019838\n",
      "Train Epoch: 3 [19200/60000 (32%)]\tLoss: 0.081031\n",
      "Train Epoch: 3 [25600/60000 (43%)]\tLoss: 0.005891\n",
      "Train Epoch: 3 [32000/60000 (53%)]\tLoss: 0.030291\n",
      "Train Epoch: 3 [38400/60000 (64%)]\tLoss: 0.008084\n",
      "Train Epoch: 3 [44800/60000 (75%)]\tLoss: 0.025313\n",
      "Train Epoch: 3 [51200/60000 (85%)]\tLoss: 0.040406\n",
      "Train Epoch: 3 [57600/60000 (96%)]\tLoss: 0.028825\n",
      "\n",
      "Test set: Average loss: 0.0000, Accuracy: 9856/10000 (98.56%)\n",
      "\n",
      "Train Epoch: 4 [0/60000 (0%)]\tLoss: 0.016187\n",
      "Train Epoch: 4 [6400/60000 (11%)]\tLoss: 0.010413\n",
      "Train Epoch: 4 [12800/60000 (21%)]\tLoss: 0.015745\n",
      "Train Epoch: 4 [19200/60000 (32%)]\tLoss: 0.059284\n",
      "Train Epoch: 4 [25600/60000 (43%)]\tLoss: 0.003621\n",
      "Train Epoch: 4 [32000/60000 (53%)]\tLoss: 0.014301\n",
      "Train Epoch: 4 [38400/60000 (64%)]\tLoss: 0.005118\n",
      "Train Epoch: 4 [44800/60000 (75%)]\tLoss: 0.023730\n",
      "Train Epoch: 4 [51200/60000 (85%)]\tLoss: 0.080267\n",
      "Train Epoch: 4 [57600/60000 (96%)]\tLoss: 0.016929\n",
      "\n",
      "Test set: Average loss: 0.0000, Accuracy: 9845/10000 (98.45%)\n",
      "\n",
      "Train Epoch: 5 [0/60000 (0%)]\tLoss: 0.058354\n",
      "Train Epoch: 5 [6400/60000 (11%)]\tLoss: 0.015700\n",
      "Train Epoch: 5 [12800/60000 (21%)]\tLoss: 0.054272\n",
      "Train Epoch: 5 [19200/60000 (32%)]\tLoss: 0.016981\n",
      "Train Epoch: 5 [25600/60000 (43%)]\tLoss: 0.004058\n",
      "Train Epoch: 5 [32000/60000 (53%)]\tLoss: 0.001284\n",
      "Train Epoch: 5 [38400/60000 (64%)]\tLoss: 0.060912\n",
      "Train Epoch: 5 [44800/60000 (75%)]\tLoss: 0.041252\n",
      "Train Epoch: 5 [51200/60000 (85%)]\tLoss: 0.049437\n",
      "Train Epoch: 5 [57600/60000 (96%)]\tLoss: 0.027513\n",
      "\n",
      "Test set: Average loss: 0.0000, Accuracy: 9844/10000 (98.44%)\n",
      "\n"
     ]
    }
   ],
   "source": [
    "# 训练模型\n",
    "epochs = 5\n",
    "for epoch in range(1, epochs + 1):\n",
    "    train(model, device, train_loader, optimizer, criterion, epoch)\n",
    "    eval(model, device, test_loader, criterion)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "该步骤并不用一定执行，仅仅是如果像保存的话。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "模型已保存为: mnist_cnn.pt\n"
     ]
    }
   ],
   "source": [
    "# 保存模型\n",
    "torch.save(model.state_dict(), \"./checkpoint//mnist_cnn.pt\")\n",
    "print(\"模型已保存为: mnist_cnn.pt\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAABcAAAAExCAYAAABbMgFNAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy81sbWrAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAokElEQVR4nO3daZCV5ZkG4KelERBNREBBY9Eu5c6mYjTuYpQoiyAqFZ2oKBo1Ex1ckrjhjmMyrhO3EQXRUscNEQkaFVBrYhCXRHCZESNi4gJuEQQF+swPCyIB/V66T/fpfrmuKqvi6buf7+2D/aS5++vTVaVSqRQAAAAAAJCZtSp9AAAAAAAAaAgKcAAAAAAAsqQABwAAAAAgSwpwAAAAAACypAAHAAAAACBLCnAAAAAAALKkAAcAAAAAIEsKcAAAAAAAsqQABwAAAAAgSwrweho9enRUVVUt/6e6ujq+973vxbHHHht//etfG+UMNTU1ccwxx9TpfS+44IIVzv/P/9x9992rNe+YY4751nnL/qnreRtaTU3NN565devWlT4erLbmvqOef/75OOWUU6Jr166x3nrrxUYbbRT7779/PPnkk3Wa19x31C233BKHHHJI1NTURJs2bWLLLbeMk046Kd59991KHw3qpLnvqIiIc889N/r27RubbLJJvfdHc99RM2fOjJNPPjl22223aNu2bVRVVcWUKVMqfSyosxx21OLFi+PCCy+MmpqaaNWqVWyzzTZx3XXX1WlWc99RERFvvvlmDBo0KNZff/1Yd91144c//GG88MILlT4W1EkOO+rrHn/88eUfy7x581b7/XPYUV931FFHRVVVVfTt27fSR8lCdaUPkIvbbrstttlmm1i4cGE89dRTMXLkyJg6dWq8/PLL0bZt20of7xsdf/zx0adPn5UeHzZsWMyaNWuVb/s25513Xvz0pz9d/u8vvPBCnHLKKXHZZZfFvvvuu/zxjh071v3QDejBBx+ML774YoXH3n777TjiiCNi4MCBFToV1F9z3VF33XVXTJs2LYYOHRrdu3ePBQsWxI033hi9e/eOMWPGxE9+8pPVmtfcd9SIESNi3333jcsuuyw22WSTeP311+Piiy+Ohx56KF588cXYaKONKn1EqJPmuqMiIq666qro1q1b9O/fP2699dZ6zWruO2r69Okxbty46NmzZ/Tu3TsefvjhSh8JyqI576iTTz45xo4dGxdffHH06tUrHn300Tj11FPjs88+i7PPPnu1ZjX3HTV37tzYc889o127dnHrrbdG69atY+TIkbHPPvvEc889F1tvvXWljwh10px31DLz58+PYcOGxcYbbxx/+9vf6jSjue+or3vkkUdi3Lhx8Z3vfKfSR8lHiXq57bbbShFReu6551Z4/LzzzitFROmOO+74xvddsGBBWc7QpUuX0tFHH12WWaVSqfSXv/ylVFVVVTrqqKPqPWvy5MmliCjde++935r7/PPPS7W1tfW+XkO44IILShFRevzxxyt9FFhtzX1Hvf/++ys9tmTJklK3bt1KW2yxRT1P1vx21Kqej+eee64UEaWLL764AieC+mnuO6pUKpWWLl26/H+3bdu2rF+TNbcd9fXn4t577y1FRGny5MmVOxDUU3PfUTNmzChVVVWVLrvsshUeHzZsWKlNmzalDz/8sF5na2476swzzyy1bNmy9NZbby1/7NNPPy116NChdPjhh1fwZFA3zX1Hfd0pp5xS6tmzZ+ncc88tRURp7ty59Z7Z3HbUMp988klpk002KV155ZWlLl26lA4++OBKHykLXgKlgey6664RETF79uyI+OpHMdZdd914+eWX44ADDoj11lsvevfuHRERX375ZVxyySWxzTbbRKtWraJjx45x7LHHxty5c1eYuXjx4jjrrLOiU6dOsc4668Qee+wR06ZNK/vZb7311iiVSnH88ceXfXbEP35M57HHHouhQ4dGx44dY5111okvvvgijjnmmKipqVnpfZa9VMvXlUqluP7666NHjx7Rpk2baNeuXQwePDjefPPNsp21VCrFbbfdFptvvnnst99+ZZsLldZcdtSGG2640mMtWrSInXbaKebMmVOv2d+kKe+oVT0fO+20U7Ro0aLBng+ohOayoyIi1lqrcb+cbso7qrGfC6iU5rKjxo0bF6VSKY499tgVHj/22GNj4cKFMWnSpHrNX5WmvKMefPDB2G+//aJLly7LH/vOd74TgwYNiocffjiWLFlS59nQlDSXHbXM008/HTfffHPccsst0aJFi7LM/CZNeUctc/rpp0fnzp3j5z//eb1n8Q++Sm0gb7zxRkSs+KMVX375ZfTv3z/222+/eOihh+LCCy+M2traGDBgQFx++eXx4x//OB555JG4/PLL4/e//33ss88+sXDhwuXvP2zYsPjNb34TP/nJT+Khhx6KQw89NAYNGhQff/zxStevqalZ5Sdukdra2hg9enRsueWWsffee6/+B74ahg4dGi1btoyxY8fGfffdFy1btlyt9z/xxBPjtNNOi/333z/GjRsX119/fcycOTN+8IMfxPvvv788N2XKlKiqqooLLrhgtc/4+OOPx+zZs2Po0KErLTxozprrjoqIWLJkSTz99NOx/fbb1+n9UzWHHRURMXXq1Fi6dGmDPx/QmJrzjmoszWVHQY6ay46aMWNGdOzYMTp16rTC4926dVv+9obS1HbUwoULY9asWcs/9q/r1q1bLFy4sKw3UkElNZcdFfHV5+Zxxx0Xp512Wuy44471+8BXQ1PbUcs8/vjjcfvttzfKNwPWNF4DvEyWLl0aS5YsiUWLFsXUqVPjkksuifXWWy/69++/PLN48eI4//zzV/gO/N133x2TJk2K+++/PwYNGrT88e7du0evXr1i9OjRcdJJJ8Vrr70WY8aMiX/7t3+LK664IiIifvjDH8ZGG20URx555Ernqa6u2x/tY489FnPmzImRI0fW6f1XR+/eveOmm26q0/s+++yz8V//9V/xH//xHzF8+PDlj++5556x1VZbxZVXXhn//u//HhERVVVV0aJFizrdlTRq1Kho0aJFs/klCfBNctlREV99B/6NN96IcePG1XlGiuawoz777LM4+eSTY9NNN42hQ4fW6azQFOS0oxpLc9hRkIvmuqM+/PDD2GCDDVZ6vG3btrH22mvHhx9+mPwcrK6mtqM+/vjjKJVKq3w+lj3WkM8HNKTmuqMivnrd7qVLl8aFF15Ylw+9zprajor4x+ugn3HGGdG9e/c6nY1v1vS/um8mlv2IyTJdu3aNG264YaVfSHbooYeu8O8TJkyI9ddfP/r167fCj1z16NEjOnXqFFOmTImTTjopJk+eHBGx0nI5/PDD4+ijj17pPMu+47e6Ro0aFdXV1Y1S+P7zc7E6JkyYEFVVVXHUUUet8Lx16tQpunfvHlOmTFn+2N57712nH2f76KOPYty4cdGnT5/YZJNN6nxWaApy2VG33HJLXHrppXH66afHgAED6jQjVVPfUYsWLYpBgwbF7Nmz48knn4x11123zueFSstlRzWmpr6jICfNeUd920+xNuRPuDbVHVWp5wMaUnPdUdOmTYurr746Jk2aFG3atEl6n3Jpijvql7/8ZbRs2TLOP//8Op+Nb6YAL5Pbb789tt1226iuro6NNtooOnfuvFJmnXXWWek3uL7//vvxySefxNprr73KufPmzYuIf3w3+p9/fK26ujrat29fjg8h5s2bF+PHj4+DDz54pes0hFU9R6nef//9KJVKKy30ZTbffPM6z17mjjvuiC+++KLBXgsdGlMOO+q2226LE088MU444YT49a9/XZaZ36Yp76gvvvgiBg4cGM8880xMmDAhvv/979drHlRaDjuqsTXlHQW5aa47qn379vHSSy+t9PiCBQviyy+/XOXd0OXS1HZUu3btoqqqapV3eX/00UcREQ36fEBDaq47aujQoTFo0KDYeeed45NPPomIr27yiYj4+9//Hq1atYr11luvzvO/TVPbUdOmTYvrr78+HnjggVi0aNHy56G2tjaWLFkSn3zySbRp0yZatWpV53Ov6RTgZbLtttvGzjvv/K2ZVX1HuUOHDtG+fftv/AUkyz7Zly2V9957b4W7kZcsWVK2H9UaO3ZsfPnll41W+K7q+WjdunV88cUXKz2+bPEu06FDh6iqqoqnn356lQugHEth1KhRsdFGG0Xfvn3rPQsqrbnvqNtuuy2OP/74OProo+PGG29slDt0muqO+uKLL+KQQw6JyZMnx0MPPbT8F9hAc9bcd1QlNNUdBTlqrjuqa9eucffdd8d77723QnH18ssvR0TEDjvsUOfZRZrajmrTpk1sueWWyz/2r3v55ZejTZs2vvlHs9Vcd9TMmTNj5syZce+99670ti222CK6d+++ym/ilUNT21GvvPJKlEqlGDhw4EpvmzNnTrRr1y6uuuqqOO2001Z7Nl9RgFdY37594+67746lS5d+6x18++yzT0RE3HnnnbHTTjstf/y///u/y/ZjqaNGjYqNN944fvSjH5VlXl3U1NTEBx98EO+///7y76Z9+eWX8eijj66Q69u3b1x++eXx17/+NQ4//PCyn2P69Onx5z//Oc4666xm8Tqg0FCawo4aPXp0HH/88XHUUUfFLbfcUtEfT630jlp25/eTTz4ZDzzwQBx44IFlmw3NUVPYUU1JpXcUsKJK76gBAwbEueeeG2PGjIlf/OIXyx8fPXp0tGnTJvr06VPn2XVR6R01cODAuPrqq2POnDmx6aabRsRXv0/lgQceiP79+/t7H2ucSu+oZS+t8nWjR4+OMWPGxLhx4xr9pWgruaP69OmzyudjyJAhsdlmm8XIkSNjyy23LMu11lQ2fIUNGTIk7rzzzjjooIPi1FNPjV122SVatmwZ77zzTkyePDkGDBgQAwcOjG233TaOOuqouPrqq6Nly5ax//77x4wZM+I3v/nNSj/GEhHLPzFSX3vpj3/8Y8ycOTPOPvvsb/xNs1OmTIl99903RowYkfwbbFfXEUccEeeff34MGTIkzjzzzFi0aFFce+21sXTp0hVyu+++e5xwwglx7LHHxvTp02OvvfaKtm3bxrvvvhvPPPNMdO3aNU466aSIiJg6dWr07t07zj///OTXUho1alRERBx33HHl/QChman0jrr33nvjuOOOix49esSJJ54Y06ZNW+HtPXv2XP4d9jVhRw0ePDh+97vfxTnnnBPt27ePZ599dvnbvvOd78R2221X/g8amrBK76iIrz6H586dGxFf/RKq2bNnx3333RcRX73uY8eOHSNizdhRn3/+eUycODEiYvl+mjp1asybNy/atm1b0ZssoBIqvaO23377OO6442LEiBHRokWL6NWrVzz22GNx8803xyWXXLLCS36sCTvqjDPOiLFjx8bBBx8cF110UbRq1Souv/zyWLRoUYN9zNCUVXpHLSvWv27Z62fvvvvu0aFDhxUez3lHderUaZUvRdy6deto3779Kp8rVo8CvMJatGgR48ePj2uuuSbGjh0bI0eOjOrq6vje974Xe++9d3Tt2nV5dtlLcowePTquvfba6NGjR9x///0xZMiQleau7nfhRo0aFVVVVd9a+M6fPz8i6vdaSUU222yzeOihh+Lss8+OwYMHR+fOnWP48OExd+7clX4r8E033RS77rpr3HTTTXH99ddHbW1tbLzxxrH77rvHLrvssjxXKpVi6dKlUVtbm3SGhQsXxl133RV77bVXbLXVVmX9+KC5qfSOeuSRR6K2tjZeeOGF2H333Vd6+1/+8peoqamJiDVjR02YMCEiIi699NK49NJLV3jb3nvvvcIvXIE1QaV3VETEiBEjYurUqcv/fcqUKcs/FydPnrz8Lyxrwo764IMP4rDDDlvhsWV/Se3SpUu89dZb9f4YoTlpCjvq+uuvj0022SSuu+66eO+996Kmpiauueaa+Nd//dcVcmvCjurYsWM8/fTTccYZZ8TRRx8dS5Ys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gCxVV/oANK4WLVoUZiZNmlSY2WyzzZKuN2vWrMLMeeedlzQLaL7+/Oc/V/oIdXbvvfcm5d59993CzEYbbZQ064gjjkjK5e69995Lyl166aUNfBJyt8ceeyTlOnXq1MAnASrphhtuSMpdccUVZbvmhAkTCjO1tbVlu145ZzXF60VE3HjjjY1+TaB5qqqqKmsuxYwZM8o2i3TuAAcAAAAAIEsKcAAAAAAAsqQABwAAAAAgSwpwAAAAAACypAAHAAAAACBLCnAAAAAAALKkAAcAAAAAIEsKcAAAAAAAsqQABwAAAAAgS9WVPgCNa4sttijM7LTTTmW73vDhwwszs2bNKtv1gDQTJ04szAwYMKARTtL0HXbYYZU+wiotWbIkKVdbW1u2a44fP74wM3369LJd7+mnny7bLPg2AwcOTMq1aNGiMPPiiy8WZp566qmk6wGN64EHHkjKnXnmmYWZjh071vc4WZg7d25S7tVXXy3MnHDCCUmz3n333aQcQKlUKmuOpssd4AAAAAAAZEkBDgAAAABAlhTgAAAAAABkSQEOAAAAAECWFOAAAAAAAGRJAQ4AAAAAQJYU4AAAAAAAZEkBDgAAAABAlqorfQDKo0uXLkm5xx57rCzXO/PMM5NyEyZMKMv1gPIaNGhQYeass85KmtWyZcv6Hme1bL/99oWZI444ohFOsqJbb721MPPWW2+V7Xr3339/Uu61114r2zWhOVpnnXUKMwcddFDZrnffffcVZpYuXVq26wHlM3v27KTckCFDCjOHHHJI0qxTTz01KddcXXrppUm53/72tw18EoCVtW7dumyzFi5cWLZZlJ87wAEAAAAAyJICHAAAAACALCnAAQAAAADIkgIcAAAAAIAsKcABAAAAAMiSAhwAAAAAgCwpwAEAAAAAyJICHAAAAACALCnAAQAAAADIUlWpVColBauqGvos1MOll16alPvVr35VluvtsssuSbnp06eX5Xo0fYmrpMHYUcC3saPWXC1btizMTJ06NWnWBx98UJj58Y9/XJj5/PPPk67HmsOOWnP16dOnMHPCCSckzerXr19hZvz48YWZm2++Oel6Kf/dvPLKK0mz3n777aQclWFHkav33nsvKVddXV2Yufjii5NmXXPNNUk50qXsKHeAAwAAAACQJQU4AAAAAABZUoADAAAAAJAlBTgAAAAAAFlSgAMAAAAAkCUFOAAAAAAAWVKAAwAAAACQJQU4AAAAAABZqiqVSqWkYFVVQ5+Fb7DHHnsUZiZOnJg0a911163vcSIiYpdddknKTZ8+vSzXo+lLXCUNxo4Cvo0dBTRldhTQlNlR5Orhhx9Oyl155ZWFmcmTJ9f3ONRRyo5yBzgAAAAAAFlSgAMAAAAAkCUFOAAAAAAAWVKAAwAAAACQJQU4AAAAAABZUoADAAAAAJAlBTgAAAAAAFlSgAMAAAAAkCUFOAAAAAAAWaqu9AEotueeexZm1l133bJdb9asWYWZ+fPnl+16AAAAANCY+vXrV+kj0EjcAQ4AAAAAQJYU4AAAAAAAZEkBDgAAAABAlhTgAAAAAABkSQEOAAAAAECWFOAAAAAAAGRJAQ4AAAAAQJYU4AAAAAAAZKm60gegcf3pT38qzPTu3bsw89FHH5XjOAAAAAAADcYd4AAAAAAAZEkBDgAAAABAlhTgAAAAAABkSQEOAAAAAECWFOAAAAAAAGRJAQ4AAAAAQJYU4AAAAAAAZEkBDgAAAABAlhTgAAAAAABkqapUKpWSglVVDX0WoBlLXCUNxo4Cvo0dBTRldhTQlNlRQFOWsqPcAQ4AAAAAQJYU4AAAAAAAZEkBDgAAAABAlhTgAAAAAABkSQEOAAAAAECWFOAAAAAAAGRJAQ4AAAAAQJYU4AAAAAAAZKmqVCqVKn0IAAAAAAAoN3eAAwAAAACQJQU4AAAAAABZUoADAAAAAJAlBTgAAAAAAFlSgAMAAAAAkCUFOAAAAAAAWVKAAwAAAACQJQU4AAAAAABZUoADAAAAAJCl/wc1YR3iKVlvlgAAAABJRU5ErkJggg==",
      "text/plain": [
       "<Figure size 1500x300 with 5 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 调用可视化函数进行验证\n",
    "visualize_predictions(model, device, test_loader)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "science39",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.18"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
